package com.warmguard.core.service.impl;



import com.warmguard.core.config.MinioProperties;
import com.warmguard.core.service.FileService;
import io.minio.*;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.XmlParserException;
import org.apache.commons.math3.exception.InsufficientDataException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.ErrorResponseException;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.rmi.ServerException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private MinioClient minioClient;
    @Autowired
    private MinioProperties properties;

    @Override
    public String upload(MultipartFile file) throws Exception {

            //判断有米有这个桶
            boolean b = minioClient.bucketExists(BucketExistsArgs.builder().bucket(properties.getBucketName()).build());
            if (!b){
                //没有就创建一共
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(properties.getBucketName())
                        .build());
                //设定权限
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().
                        bucket(properties.getBucketName())
                        .config(createBucketPolicyConfig(properties.getBucketName()))
                        .build());
                //

            }
            InputStream inputStream = file.getInputStream();
            String fileName = new SimpleDateFormat("yyyyMMdd").format(new Date()) +
                    "/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
//                该方法把本地磁盘文件上传到minio
//                minioClient.uploadObject(null);
            //这个可以把一个流上传到 minio的object里面
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(properties.getBucketName())
                    .object(fileName)
                    .stream(inputStream, file.getSize(), -1)
                    //用于描述文件的数据类型，例如文本文件、图片文件、视频文件等。设置了响应的 MIME 类型，以便浏览器或其他客户端知道如何处理下载的文件。
                    .contentType(file.getContentType())
                    .build());
             return String.join("/", properties.getEndpoint(), properties.getBucketName(), fileName);


    }
    private String createBucketPolicyConfig(String bucketName) {

        //用于授予对某个存储桶（bucket）中所有对象的读取权限。
        /*
        Action: "s3:GetObject"  表示允许的操作，这里是获取对象（GetObject）
        Effect: "Allow" 表示这个策略语句允许指定的操作。
        principal: "*" 表示任何主体（用户、服务、角色等）都可以执行这个操作。* 是一个通配符，表示所有主体。
        Resource: "arn:aws:s3:::%s/*" 表示资源范围。arn:aws:s3:::%s/* 是一个 Amazon S3 资源标识符，其中 %s 是一个占位符，会被 bucketName 变量的值替换。arn:aws:s3:::%s/* 表示指定存储桶中的所有对象。
        允许任何主体对指定存储桶中的所有对象执行 GetObject 操作。这个策略通常用于授予对存储桶中所有对象的读取权限

         */
        return """
            {
              "Statement" : [ {
                "Action" : "s3:GetObject",
                "Effect" : "Allow",
                "Principal" : "*",
                "Resource" : "arn:aws:s3:::%s/*"
              } ],
              "Version" : "2012-10-17"
            }
            """.formatted(bucketName);
    }
}
